/* ========================= eCAL LICENSE =================================
 *
 * Copyright (C) 2016 - 2020 Continental Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * ========================= eCAL LICENSE =================================
*/

/**
 * eCALSys Service
**/

#include "ecalsys_service.h"
#include "ecalsys/ecal_sys_logger.h"

#include <ecalsys/proto_helpers.h>

namespace
{
  std::list<std::shared_ptr<EcalSysTask>> GetAllTasks()
  {
    auto tasks   = Globals::EcalSysInstance()->GetTaskList();
    auto options = Globals::EcalSysInstance()->GetOptions();

    if (options.local_tasks_only)
    {
      // Remove all non-local tasks
      tasks.remove_if(
        [](std::shared_ptr<EcalSysTask> task)
      {
        return QString::compare(task->GetTarget().c_str(), eCAL::Process::GetHostName().c_str(), Qt::CaseSensitivity::CaseInsensitive) != 0;
      });
    }
    return tasks;
  }

  std::list<std::shared_ptr<EcalSysTask>> GetRequestedTasks(const ::eCAL::pb::sys::TaskRequest* request)
  {
    std::set<std::shared_ptr<EcalSysTask>> tasks;
    for (int32_t id : request->tids())
    {
      tasks.emplace(Globals::EcalSysInstance()->GetTask(id));
    }
    for (std::string task_name : request->tnames())
    {
      for (auto& task : Globals::EcalSysInstance()->GetTaskList())
      {
        if (task->GetName() == task_name)
        {
          tasks.emplace(task);
        }
      }
    }
    return std::list<std::shared_ptr<EcalSysTask>>(tasks.begin(), tasks.end());
  }
}

void eCALSysServiceImpl::StartTasks(::google::protobuf::RpcController* /*controller*/,
  const ::eCAL::pb::sys::TaskRequest* request,
  ::eCAL::pb::sys::Response* response,
  ::google::protobuf::Closure* /*done*/)
{
  bool all_tasks(request->all());
  if (all_tasks)
  {
    EcalSysLogger::Log("eCALSysServiceImpl::StartTasks - start all tasks");
    Globals::EcalSysInstance()->StartTaskList(GetAllTasks());
  }
  else
  {
    EcalSysLogger::Log("eCALSysServiceImpl::StartTasks - start list of tasks");
    Globals::EcalSysInstance()->StartTaskList(GetRequestedTasks(request));
  }
  emit ecalsysgui_instance->startStopActionTriggeredSignal();

  response->set_result(eCAL::pb::sys::Response::success);
}

void eCALSysServiceImpl::StopTasks(::google::protobuf::RpcController* /*controller*/,
  const ::eCAL::pb::sys::TaskRequest* request,
  ::eCAL::pb::sys::Response* response,
  ::google::protobuf::Closure* /*done*/)
{
  bool all_tasks(request->all());
  if (all_tasks)
  {
    EcalSysLogger::Log("eCALSysServiceImpl::StopTasks - stop all tasks");
    Globals::EcalSysInstance()->StopTaskList(GetAllTasks(), true, true);
  }
  else
  {
    EcalSysLogger::Log("eCALSysServiceImpl::StartTasks - stop list of tasks");
    Globals::EcalSysInstance()->StopTaskList(GetRequestedTasks(request), true, true);
  }
  emit ecalsysgui_instance->startStopActionTriggeredSignal();

  response->set_result(eCAL::pb::sys::Response::success);
}

void eCALSysServiceImpl::RestartTasks(::google::protobuf::RpcController* /*controller*/,
  const ::eCAL::pb::sys::TaskRequest* request,
  ::eCAL::pb::sys::Response* response,
  ::google::protobuf::Closure* /*done*/)
{
  bool all_tasks(request->all());
  if (all_tasks)
  {
    EcalSysLogger::Log("eCALSysServiceImpl::RestartTasks - restart all tasks");
    Globals::EcalSysInstance()->RestartTaskList(GetAllTasks(), true, true);
  }
  else
  {
    EcalSysLogger::Log("eCALSysServiceImpl::RestartTasks - restart list of tasks");
    Globals::EcalSysInstance()->RestartTaskList(GetRequestedTasks(request), true, true);
  }
  emit ecalsysgui_instance->startStopActionTriggeredSignal();

  response->set_result(eCAL::pb::sys::Response::success);
}

void eCALSysServiceImpl::GetStatus(::google::protobuf::RpcController* /*controller*/,
  const ::eCAL::pb::sys::GenericRequest* /*request*/,
  ::eCAL::pb::sys::State* response,
  ::google::protobuf::Closure* /*done*/)
{
  eCAL::sys::proto_helpers::ToProtobuf(*response, *Globals::EcalSysInstance());
}
